/*
 * Copyright (C)
 */
package buss.console.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

/**
 * 合伙伙伴辅助工具
 * 
 * @author 周武
 */
public class PartnerHelper {

    /**
     * 
     * 签名
     * 
     * @param params 参与签名的参数
     * @param secret 签名使用的密钥
     * @return 签名值
     */
    public static String sign(Map<String, String> params, String secret) {
        if (secret == null || "".equals(secret)) {
            throw new IllegalArgumentException("secret can not be empty");
        }
        if (params == null) {
            throw new IllegalArgumentException("params can not be null");
        }
        StringBuilder sb = new StringBuilder();
        List<String> paramNames = new ArrayList<String>(params.size());
        paramNames.addAll(params.keySet());
        Collections.sort(paramNames);
        for (String paramName : paramNames) {
            sb.append('&').append(paramName).append('=').append(params.get(paramName));
        }
        try {
            byte[] dataBytes = (sb.length() > 0 ? sb.substring(1) : "").getBytes("UTF-8");
            byte[] secretBytes = secret.getBytes("UTF-8");
            return bytes2Hexstr(calcMac(dataBytes, secretBytes));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("不支持UTF-8");
        }
    }

    /**
     * 
     * 计算消息鉴别码<BR>
     * 使用HMACSHA1算法
     * 
     * @param data 数据块
     * @param secret 密钥块
     * @return 消息摘要块
     */
    public static byte[] calcMac(byte[] data, byte[] secret) {
        try {
            SecretKeySpec secretKey = new SecretKeySpec(secret, "HMACSHA1");
            Mac mac = Mac.getInstance("HMACSHA1");
            mac.init(secretKey);
            return mac.doFinal(data);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("不支持HMACSHA1");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 
     * 从PinBlock解密Pin<BR>
     * 符合ANSI X9.8标准<BR>
     * 已与加密机配合测试通过
     * 
     * @param cardNo 卡号（纯数字、至少1位）
     * @param pinBlock Pin密文（长度为16的十六进制字符串、表示8个字节）
     * @param desKey 二倍长3DES密钥（长度为32的十六进制字符串、表示16个字节）
     * @return 明文Pin（纯数字、4~12位）
     * @throws Exception 参数不合法或解密有误时抛出异常
     */
    public static String decryptPinFromPinBlock(String cardNo, String pinBlock, String desKey) throws Exception {
        SecretKey key = new SecretKeySpec(hexstr2Bytes(desKey + desKey.substring(0, 16)), "TripleDES");
        Cipher c = Cipher.getInstance("TripleDES/ECB/NoPadding");
        c.init(Cipher.DECRYPT_MODE, key);
        byte[] raw = c.doFinal(hexstr2Bytes(pinBlock));
        byte[] acc = hexstr2Bytes(cardNo.length() > 12 ? "0000"
                + cardNo.substring(cardNo.length() - 13, cardNo.length() - 1) : "0000000000000000".substring(cardNo
                .length()) + cardNo);
        byte[] pin = new byte[8];
        for (int i = 0; i < 8; i++) {
            pin[i] = (byte) (raw[i] ^ acc[i]);
        }
        return bytes2Hexstr(pin).substring(2, 2 + pin[0]);
    }

    /**
     * 
     * 字节转十六进制字符串<BR>
     * 输出字符集合为[0-9a-f]
     * 
     * @param bytes 字节
     * @return 十六进制字符串
     */
    public static String bytes2Hexstr(byte[] bytes) {
        char[] chs = new char[bytes.length * 2];
        for (int i = 0; i < bytes.length; i++) {
            chs[2 * i] = "0123456789abcdef".charAt(bytes[i] >>> 4 & 0x0F);
            chs[2 * i + 1] = "0123456789abcdef".charAt(bytes[i] & 0x0F);
        }
        return String.valueOf(chs);
    }

    /**
     * 
     * 十六进制字符串转字节<BR>
     * 传入字符须成对，否则最后1字符将被忽略<BR>
     * 非16进制字符视作'f'
     * 
     * 
     * @param hexstr 十六进制字符串
     * @return 字节
     */
    public static byte[] hexstr2Bytes(String hexstr) {
        char[] chs = hexstr.toLowerCase().toCharArray();
        byte[] ret = new byte[chs.length / 2];
        int high, low;
        for (int i = 0; i < ret.length; i++) {
            high = "0123456789abcdef".indexOf(chs[2 * i]);
            low = "0123456789abcdef".indexOf(chs[2 * i + 1]);
            ret[i] = (byte) ((high << 4 & 0xF0) | (low & 0x0F));
        }
        return ret;
    }
    
    /**
     * 
     * 读取秘钥对入参进行数字签名
     * 秘钥由苏宁方提供
     * 
     * 
     * @param filePath 秘钥路径
     * @return 字符串
     */
    
    public static String readTxt(String filePath) {
  	  try {
  	    File file = new File(filePath);
  	    if(file.isFile() && file.exists()) {
  	      InputStreamReader isr = new InputStreamReader(new FileInputStream(file), "utf-8");
  	      BufferedReader br = new BufferedReader(isr);
  	      String lineTxt = null;
  	      while ((lineTxt = br.readLine()) != null) {
  	        return lineTxt;
  	      }
  	      br.close();
  	    } 
  	  } catch (Exception e) {
  		throw new RuntimeException(e);
  	  }
  	  	return null;
  	  }
}
